package com.nullpointer.xchatfinal.adapter;

import java.util.List;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.androidquery.AQuery;
import com.androidquery.callback.ImageOptions;
import com.nullpointer.xchatfinal.MainActivity;
import com.nullpointer.xchatfinal.R;
import com.nullpointer.xchatfinal.VideoCallActivity;
import com.nullpointer.xchatfinal.ViewImageActivity;
import com.nullpointer.xchatfinal.database.MessagesDataManager;
import com.nullpointer.xchatfinal.object.MessageContent;
import com.nullpointer.xchatfinal.object.PrivateMessageContent;
import com.nullpointer.xchatfinal.object.TargetChat;
import com.nullpointer.xchatfinal.object.MessageContent.MsgType;
import com.nullpointer.xchatfinal.object.User;
import com.nullpointer.xchatfinal.service.ChatService;
import com.nullpointer.xchatfinal.utils.Common;
import com.nullpointer.xchatfinal.utils.DataManager;
import com.nullpointer.xchatfinal.utils.Emoticons;
import com.nullpointer.xchatfinal.utils.Utils;

public class ChatAdapter extends ArrayAdapter<MessageContent> {

	private static class ViewHolder {
		public final LinearLayout rootView;
		public final LinearLayout llLeftChat;
		public final TextView tvLeftName;
		public final ImageView ivLeftAvatar;
		public final TextView tvLeftMessage;
		public final RelativeLayout rlLeftImage;
		public final ProgressBar pbLeftLoading;
		public final ImageView ivLeftImage;
		public final LinearLayout llRightChat;
		public final TextView tvRightName;
		public final TextView tvRightMessage;
		public final RelativeLayout rlRightImage;
		public final ProgressBar pbRightLoading;
		public final ImageView ivRightImage;
		public final TextView tvMessageState;
		public final ImageView ivRightAvatar;
		public final LinearLayout llInfo;
		public final TextView tvInfo;
		public final LinearLayout llAction;
		public final TextView tvActionOk;
		public final TextView tvActionCancel;

		private ViewHolder(LinearLayout rootView, LinearLayout llLeftChat,
				TextView tvLeftName, ImageView ivLeftAvatar,
				TextView tvLeftMessage, RelativeLayout rlLeftImage,
				ProgressBar pbLeftLoading, ImageView ivLeftImage,
				LinearLayout llRightChat, TextView tvRightName,
				TextView tvRightMessage, RelativeLayout rlRightImage,
				ProgressBar pbRightLoading, ImageView ivRightImage,
				TextView tvMessageState, ImageView ivRightAvatar,
				LinearLayout llInfo, TextView tvInfo, LinearLayout llAction,
				TextView tvActionOk, TextView tvActionCancel) {
			this.rootView = rootView;
			this.llLeftChat = llLeftChat;
			this.tvLeftName = tvLeftName;
			this.ivLeftAvatar = ivLeftAvatar;
			this.tvLeftMessage = tvLeftMessage;
			this.rlLeftImage = rlLeftImage;
			this.pbLeftLoading = pbLeftLoading;
			this.ivLeftImage = ivLeftImage;
			this.llRightChat = llRightChat;
			this.tvRightName = tvRightName;
			this.tvRightMessage = tvRightMessage;
			this.rlRightImage = rlRightImage;
			this.pbRightLoading = pbRightLoading;
			this.ivRightImage = ivRightImage;
			this.tvMessageState = tvMessageState;
			this.ivRightAvatar = ivRightAvatar;
			this.llInfo = llInfo;
			this.tvInfo = tvInfo;
			this.llAction = llAction;
			this.tvActionOk = tvActionOk;
			this.tvActionCancel = tvActionCancel;
		}

		public static ViewHolder create(LinearLayout rootView) {
			LinearLayout llLeftChat = (LinearLayout) rootView
					.findViewById(R.id.ll_left_chat);
			TextView tvLeftName = (TextView) rootView
					.findViewById(R.id.tv_left_name);
			ImageView ivLeftAvatar = (ImageView) rootView
					.findViewById(R.id.iv_left_avatar);
			TextView tvLeftMessage = (TextView) rootView
					.findViewById(R.id.tv_left_message);
			RelativeLayout rlLeftImage = (RelativeLayout) rootView
					.findViewById(R.id.rl_left_image);
			ProgressBar pbLeftLoading = (ProgressBar) rootView
					.findViewById(R.id.pb_left_loading);
			ImageView ivLeftImage = (ImageView) rootView
					.findViewById(R.id.iv_left_image);
			LinearLayout llRightChat = (LinearLayout) rootView
					.findViewById(R.id.ll_right_chat);
			TextView tvRightName = (TextView) rootView
					.findViewById(R.id.tv_right_name);
			TextView tvRightMessage = (TextView) rootView
					.findViewById(R.id.tv_right_message);
			RelativeLayout rlRightImage = (RelativeLayout) rootView
					.findViewById(R.id.rl_right_image);
			ProgressBar pbRightLoading = (ProgressBar) rootView
					.findViewById(R.id.pb_right_loading);
			ImageView ivRightImage = (ImageView) rootView
					.findViewById(R.id.iv_right_image);
			TextView tvMessageState = (TextView) rootView
					.findViewById(R.id.tv_message_state);
			ImageView ivRightAvatar = (ImageView) rootView
					.findViewById(R.id.iv_right_avatar);
			LinearLayout llInfo = (LinearLayout) rootView
					.findViewById(R.id.ll_info);
			TextView tvInfo = (TextView) rootView.findViewById(R.id.tv_info);
			LinearLayout llAction = (LinearLayout) rootView
					.findViewById(R.id.ll_action);
			TextView tvActionOk = (TextView) rootView
					.findViewById(R.id.tv_action_ok);
			TextView tvActionCancel = (TextView) rootView
					.findViewById(R.id.tv_action_cancel);
			return new ViewHolder(rootView, llLeftChat, tvLeftName,
					ivLeftAvatar, tvLeftMessage, rlLeftImage, pbLeftLoading,
					ivLeftImage, llRightChat, tvRightName, tvRightMessage,
					rlRightImage, pbRightLoading, ivRightImage, tvMessageState,
					ivRightAvatar, llInfo, tvInfo, llAction, tvActionOk,
					tvActionCancel);
		}
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		final ViewHolder vh;
		if (convertView == null) {
			View view = mInflater.inflate(R.layout.item_lv_chat_room, parent,
					false);
			vh = ViewHolder.create((LinearLayout) view);
			view.setTag(vh);
		} else {
			vh = (ViewHolder) convertView.getTag();
		}
		AQuery aq = new AQuery(convertView);
		final MessageContent item = getItem(position);
		Integer userID = item.getFromUserID();
		if (item.getMsgType() == MsgType.UPDATE_GROUP_INFO
				|| item.getMsgType() == MsgType.ACCEPT_VIDEO_CALL
				|| item.getMsgType() == MsgType.REJECT_VIDEO_CALL
				|| item.getMsgType() == MsgType.SEND_CHAT_VIDEO_REQUEST) {
			vh.llLeftChat.setVisibility(View.GONE);
			vh.llRightChat.setVisibility(View.GONE);
			vh.tvInfo.setVisibility(View.VISIBLE);
			vh.tvInfo.setText(item.getContent());
			vh.llInfo.setVisibility(View.VISIBLE);
			vh.llAction.setVisibility(View.GONE);
		} else if (item.getMsgType() == MsgType.RECEIVE_CHAT_VIDEO_REQUEST) {
			vh.llLeftChat.setVisibility(View.GONE);
			vh.llRightChat.setVisibility(View.GONE);
			vh.tvInfo.setVisibility(View.VISIBLE);
			vh.tvInfo.setText(item.getContent());
			vh.llInfo.setVisibility(View.VISIBLE);
			vh.llAction.setVisibility(View.VISIBLE);
			vh.tvActionOk.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					deleteVideoRequest(item);
					startVideoCallActitity(item.getFromUserID(), item.getName());
				}
			});

			vh.tvActionCancel.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					deleteVideoRequest(item);
					sendCancelVideoCall(item.getFromUserID());
				}
			});
		} else {
			vh.tvInfo.setVisibility(View.GONE);
			vh.llInfo.setVisibility(View.GONE);
			if (userID.equals(currentID)) {
				// Right content
				vh.llLeftChat.setVisibility(View.GONE);
				vh.llRightChat.setVisibility(View.VISIBLE);
				setViewContent(true, item, vh.tvRightName, vh.tvRightMessage,
						vh.ivRightAvatar, vh.ivRightImage, vh.rlRightImage,
						vh.pbRightLoading, aq, vh.llRightChat);
			} else {
				// Left content
				vh.llRightChat.setVisibility(View.GONE);
				vh.llLeftChat.setVisibility(View.VISIBLE);
				setViewContent(false, item, vh.tvLeftName, vh.tvLeftMessage,
						vh.ivLeftAvatar, vh.ivLeftImage, vh.rlLeftImage,
						vh.pbLeftLoading, aq, vh.llLeftChat);
			}
		}

		if (position == getCount() - 1) {
			vh.tvMessageState.setVisibility(View.VISIBLE);
			switch (item.getMessageState()) {
			case SENDING:
				vh.tvMessageState.setText("Sending...");
				break;
			case SENT:
				vh.tvMessageState.setText("Sent");
				break;
			case DELIVERED:
				vh.tvMessageState.setText("Delivered");
				break;
			case SEEN:
				vh.tvMessageState.setText("Seen");
				break;
			case ERROR:
				vh.tvMessageState.setText("Error");
				break;
			default:
				vh.tvMessageState.setVisibility(View.GONE);
				break;
			}
		} else {
			vh.tvMessageState.setVisibility(View.GONE);
		}

		return vh.rootView;
	}

	protected void sendCancelVideoCall(Integer fromUserID) {
		User user = DataManager.getInstance(context).getCurrentUser();
		String text = user.getName() + " has rejected the video chat.";
		PrivateMessageContent privateMessageContent = new PrivateMessageContent(
				context, text, MsgType.REJECT_VIDEO_CALL,
				Integer.toString(fromUserID));
		try {
			ChatService.getInstance().sendMessagePrivate(privateMessageContent,
					null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void startVideoCallActitity(Integer targetID, String name) {
		Intent intent = new Intent(context, VideoCallActivity.class);
		intent.putExtra(Common.ExtraKey.USER_ID, targetID);
		intent.putExtra(Common.ExtraKey.USER_NAME, name);
		intent.putExtra(Common.ExtraKey.IS_CALLER, false);
		context.startActivity(intent);
	}

	protected void deleteVideoRequest(MessageContent item) {
		if (item.getFromUserID() != null) {
			MessagesDataManager.getInstance(context)
					.deleteAllVideoCallMessagesByTargetID(item.getFromUserID());
		}
		this.remove(item);
	}

	private void setViewContent(final boolean isMyMsg,
			final MessageContent item, TextView tvName, TextView tvMessage,
			ImageView ivAvatar, ImageView ivImage, RelativeLayout rlImage,
			ProgressBar pbProgressBar, AQuery aq, LinearLayout llContent) {
		if (isChatGroup) {
			tvName.setText(item.getName());
			tvName.setVisibility(View.VISIBLE);
		} else {
			tvName.setVisibility(View.GONE);
		}

		if (item.getAvatarID() != null) {
			ImageOptions options = new ImageOptions();
			options.round = 5;
			options.fileCache = true;
			options.memCache = true;
			options.targetWidth = 48;
			options.fallback = R.drawable.ic_no_avatar;
			String url = Utils.getSmallAvatarFacebook(item.getAvatarID());
			aq.id(ivAvatar).image(url, options);

		} else {
			ivAvatar.setImageResource(R.drawable.ic_no_avatar);
		}

		ivAvatar.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// String avatarLarge = Utils.getLargeAvatarFacebook(item
				// .getAvatarID());
				// Intent intent = new Intent(context, ViewImageActivity.class);
				// intent.putExtra(Common.ExtraKey.IMAGE_URL, avatarLarge);
				// context.startActivity(intent);
				User user = new User();
				user.setUserID(item.getFromUserID());
				((MainActivity) context).viewProfile(user, isChatGroup, true);
			}
		});

		if (item.getMsgType() == MsgType.IMAGE) {
			tvMessage.setVisibility(View.GONE);
			rlImage.setVisibility(View.VISIBLE);
			if (item.getContent() != null) {
				ImageOptions options = new ImageOptions();
				options.round = 5;
				options.fileCache = true;
				options.memCache = true;
				options.targetWidth = 200;
				options.fallback = R.drawable.ic_hiden_image;
				aq.id(ivImage).progress(pbProgressBar)
						.image(item.getContent(), options);
				ivImage.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						Intent intent = new Intent(context,
								ViewImageActivity.class);
						intent.putExtra(Common.ExtraKey.IMAGE_URL,
								item.getContent());
						context.startActivity(intent);
					}
				});

				ivImage.setOnLongClickListener(new OnLongClickListener() {

					@Override
					public boolean onLongClick(View v) {
						AlertDialog.Builder aBuilder = new AlertDialog.Builder(
								context);
						String[] menu = new String[] { "Resend" };
						aBuilder.setItems(menu, new Dialog.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								switch (which) {
								case 0:
									resendMessageImage(item);
									break;
								default:
									break;
								}
							}

						});

						AlertDialog alertDialog = aBuilder.create();
						alertDialog.setCanceledOnTouchOutside(true);
						alertDialog.show();
						return true;
					}
				});
			} else {
				ivImage.setOnLongClickListener(null);
				rlImage.setVisibility(View.GONE);
			}
			llContent.setOnLongClickListener(null);
		} else {
			tvMessage.setVisibility(View.VISIBLE);
			rlImage.setVisibility(View.GONE);
			if (item.getContent() != null) {
				tvMessage.setText(Emoticons.getSmiledText(context,
						item.getContent()));
				llContent.setOnLongClickListener(new OnLongClickListener() {

					@Override
					public boolean onLongClick(View v) {
						AlertDialog.Builder aBuilder = new AlertDialog.Builder(
								context);
						String[] menu;
						if (isMyMsg) {
							menu = new String[] { "Copy message", "Resend" };
						} else {
							menu = new String[] { "Copy message" };
						}
						aBuilder.setItems(menu, new Dialog.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								switch (which) {
								case 0:
									Utils.copyTextToClipboard(context,
											item.getContent());
									break;
								case 1:
									resendMessageText(item);
								default:
									break;
								}
							}

						});

						AlertDialog alertDialog = aBuilder.create();
						alertDialog.setCanceledOnTouchOutside(true);
						alertDialog.show();
						return true;
					}
				});
			} else {
				tvMessage.setText("");
				llContent.setOnLongClickListener(null);
			}

		}
	}

	private LayoutInflater mInflater;
	private Context context;
	private Integer currentID;
	private boolean isChatGroup = true;

	// Constructors
	public ChatAdapter(Context context, List<MessageContent> objects) {
		super(context, 0, objects);
		this.context = context;
		this.mInflater = LayoutInflater.from(context);
		this.currentID = DataManager.getInstance(context).getCurrentUser()
				.getUserID();
	}

	public ChatAdapter(Context context, MessageContent[] objects) {
		super(context, 0, objects);
		this.context = context;
		this.mInflater = LayoutInflater.from(context);
		this.currentID = DataManager.getInstance(context).getCurrentUser()
				.getUserID();
	}

	public void setIsChatGroup(boolean isChatGroup) {
		this.isChatGroup = isChatGroup;
	}

	private void resendMessageText(MessageContent item) {
		try {
			TargetChat currentTargetChat = DataManager.getInstance(context)
					.getCurrentTargetChat();

			if (currentTargetChat == null) {
				return;
			}
			PrivateMessageContent privateMessageContent = new PrivateMessageContent(
					context, item.getContent(), MsgType.TEXT, currentTargetChat);
			((MainActivity) context)
					.sendMessageTextPrivate(privateMessageContent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void resendMessageImage(MessageContent item) {
		try {
			TargetChat currentTargetChat = DataManager.getInstance(context)
					.getCurrentTargetChat();

			if (currentTargetChat == null) {
				return;
			}
			PrivateMessageContent privateMessageContent = new PrivateMessageContent(
					context, item.getContent(), MsgType.IMAGE,
					currentTargetChat);
			((MainActivity) context)
					.sendMessageImagePrivate(privateMessageContent);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
